package iss.java;

/**
 * Created by WeiZehao on 16/9/29.
 */
import iss.java.list.Node;

public class TestThreadA extends Thread
{
    private Node _node;     // 获得对Node对象的引用
    private String _name;   // 线程名

    /*构造函数*/
    public TestThreadA(String name, Node node)
    {
        _name = name;
        _node = node;
    }

    /*
     * 复写run方法
     *
     * 测试说明：
     * 这个方法的目的是每次让Data自增1，循环50万次
     * 我在Main_A中开了，三个线程，data初值为0，所以正确结果应该是150万
     * 循环次数太少的时候，由于运行过快，基本观察不到三个线程交替执行的情况，且几乎不会出现线程写入数据时发生冲突
     * 为了既能观察到多线程交替执行，又能验证如果不上锁数据会被破坏，所以选择了50万次。
     *
     * 测试结果示例说明：
     *
     * 正确OUTPUT
     * Thread2写入的data值为829510    //表示data = 829510时，线程2已经执行完毕
     * Thread3写入的data值为1425784   //表示data = 1425784时，线程3已经执行完毕
     * Thread1写入的data值为1500000   //表示data = 150w时，线程1已经执行完毕
     * 线程2在data为80多万时才执行完，大于50万，说明在线程2执行完前，必然有线程1或线程3执行了一部分循环，后来暂停让给了其他线程
     * 这样就观察到了线程的交替执行
     * 在本示例中，最后执行完的是线程1，此时data为150万，说明结果正确，数据未被破坏
     * 多次测试，结果均正确，所以数据被保护
     *
     * 错误OUTPUT（把上锁和解锁语句注释掉会出现此结果）
     * Thread2执行完时data的值为549456
     * Thread1执行完时data的值为1010476
     * Thread3执行完时data的值为1221926
     * 最后data值小于预期值
     * 这是因为如果不上锁的话，多个线程有可能同时读取了一个相同的data值，并自增1写入，"浪费了"当次循环，当然还有各种其他情况
     * 多次运行会发现data值都与预期值不符，而且结果随机，所以数据被破坏了
     */

    public void run()
    {
        int storeData = 0;
        for(int i = 0; i < 500000; i++)
        {
            _node.mylock.writeLock().lock();        // 上写锁
            try {
                storeData = _node.getData();        // 获得data值
                storeData++;                        // 自增1
                _node.setData(storeData);           // 写入data值
            }
            finally {
                _node.mylock.writeLock().unlock();  // 解写锁
            }
        }// end for
        System.out.println(_name + "执行完时data的值为" + storeData);// 当前线程执行完会输出该句
    }// end method run
}// end class testThreadA
